#pragma once
#include "AudioHost.h"
#include "wavvsthost.h"
#include "kssample.h"
#include "DsoundOutput.h"

// - macros -------------------------------------------------------------
#define ThrowOnFail(hr, strErr)     if (!SUCCEEDED((hr))) throw (strErr) 
#define ThrowOnNull(p, strErr)      if (NULL == p) throw (strErr) 

#define Zero(s)                     ZeroMemory(&s, sizeof(s))

// - enums, structs, etc. -----------------------------------------------
enum {
	eRun,
	eStop,
};

struct DATA_PACKET
{
    KSSTREAM_HEADER Header;
    OVERLAPPED      Signal;
};

class CAudioHostForKS:
	public CAudioHost
{
protected:
	enum OUTPUT_DRIVER_TYPE{
		DIRECT_SOUND,
		KERNEL_STREAM,
		CORE_AUDIO
	};
public:
	CAudioHostForKS(void);
	~CAudioHostForKS(void);
	
protected:
	HRESULT CreateEnumRen();
	HRESULT CreateEnumCap();
	BOOL CreatePins(void);
	void PinFromWfx(WAVEFORMATEXTENSIBLE* pwfx);
	void DeletePins(void);
	HANDLE CreateWorkThreads(LPTHREAD_START_ROUTINE lpThreadProc);
protected:
	CDsoundOutput*		m_pDSO;
	OUTPUT_DRIVER_TYPE	m_eDrvType;
	CKsEnumFilters*		m_pEnumerator;
	CKsEnumFilters*		m_pCEnumerator;
	CKsAudRenFilter*    m_pFilter;
	CKsAudRenPin*       m_pPin;
	CKsAudCapFilter*    m_pCFilter;
	CKsAudCapPin*       m_pCPin;
	BOOL				m_fIsVista;
	int					m_nLDevs;
	char				m_pszLDevNames[16][128];
	int					m_nCDevs;
	char				m_pszCDevNames[16][128];
	HANDLE				m_hControlEvents[2];
	BOOL				m_fIsRun;
	int					m_iCurLDev;
	int					m_iCurCDev;
	CWavVstHost**		m_pVSTArray;
	HANDLE				m_hThread;
	int					m_nBufferSize;
	CRITICAL_SECTION	m_cs;//Used for volume
	int					m_iInChannels;
	int					m_nVolume;
	WAVEFORMATEX		m_wfx;
	int					m_nVST;

	const int			MAX_BUFFER_SIZE;
	const int			MIN_BUFFER_SIZE;

	BOOL				m_fVstChanged;
public:
	friend DWORD WINAPI WorkThreadProc(LPVOID pParam);

	int GetListenDeviceCount(void);
	int GetCaptureDeviceCount(void);
	char* GetListenDeviceName(int i);
	char* GetCaptureDeviceName(int i);

	int GetCurrentListenDevice(void);
	BOOL SetCurrentListenDevice(int i);
	BOOL SetCurrentListenDeviceByName(char* szDeviceName);
	int GetCurrentCaptureDevice(void);
	BOOL SetCurrentCaptureDevice(int i);
	BOOL SetCurrentCaptureDeviceByName(char* szDeviceName);
	BOOL Start(void);
	void Stop(void);
	
	BOOL SetVstEffect(CWavVstHost** pVSTArray,int nCount);

	BOOL SetBufferSize(int size);
	int GetBufferSize(){return m_nBufferSize;};
	int GetBufferSizeBySampleCount(){return m_nBufferSize/m_wfx.nBlockAlign;};
	BOOL SetBufferSizeBySampleCount(int samples){return SetBufferSize(samples*m_wfx.nBlockAlign);};
	int SetVolume(int Vol);//0-100
	int GetVolume(void);
	BOOL SetFormat(WAVEFORMATEX* pwfx);
	void GetFormat(WAVEFORMATEX* pwfx);
	BOOL UseDirectSoundOutput(BOOL fUseDirectSoundOutput);
};
